package org.example.filter;


import lombok.extern.slf4j.Slf4j;
import org.example.skytool.security.JwtUtils;
import org.example.dao.dto.log.EsLog;
import org.example.exception.PassErrorException;
import org.example.skytool.commom.IpUtil;
import org.example.skytool.commom.RegexUtils;
import org.example.skytool.commom.StringUtil;
import org.example.skytool.date.TimeZoneUtil;
import org.example.skytool.json.JackSonUtil;
import org.example.skytool.security.ThreadLocalUtil;
import org.example.skytool.security.WhiteList;
import org.example.utils.user.RedisUserService;

import javax.annotation.Resource;
import javax.servlet.*;
import javax.servlet.http.HttpServletRequest;
import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStream;
import java.io.InputStreamReader;

@Slf4j
public class RequestFilter implements Filter {

    @Resource
    private ThreadLocalUtil threadLocalUtil;


    @Resource
    private WhiteList whiteList;

    @Resource
    private RedisUserService redisUserService;

    @Resource
    TimeZoneUtil timeZoneUtil;

    @Override
    public void init(FilterConfig filterConfig) throws ServletException {
        Filter.super.init(filterConfig);
    }



    public void printBasicInfo(ServletRequest s) {
        EsLog esLog = new EsLog();
        esLog.setDate(timeZoneUtil.getNowTime());
        HttpServletRequest request = (HttpServletRequest) s;
        esLog.setIp(IpUtil.getIpAddr(request));
        String method = request.getMethod();
        esLog.setHttpMethod(method);
        String path = request.getRequestURI();
        esLog.setHttpPath(path);
        String contentType = request.getContentType();
        esLog.setHttpContentType(contentType);
        String header = request.getHeader("token");
        esLog.setHttpHeader(header);
        if("application/json".equals(contentType)){
            StringBuilder stringBuilder = new StringBuilder();
            BufferedReader bufferedReader = null;
            try {
                InputStream inputStream = request.getInputStream();
                if (inputStream != null) {
                    bufferedReader = new BufferedReader(new InputStreamReader(inputStream));
                    char[] charBuffer = new char[128];
                    int bytesRead = -1;
                    while ((bytesRead = bufferedReader.read(charBuffer)) > 0) {
                        stringBuilder.append(charBuffer, 0, bytesRead);
                    }
                } else {
                    stringBuilder.append("");
                }
            } catch (IOException ex) {

            } finally {
                if (bufferedReader != null) {
                    try {
                        bufferedReader.close();
                    } catch (IOException ex) {

                    }
                }
            }
            String body = stringBuilder.toString();
            body = JackSonUtil.encode(body);
            if (body != null) {
                esLog.setHttpBodyMeg(body);
            } else {
            }
        }else{
        }
        log.info(esLog.toString1());
    }

    @Override
    public void doFilter(ServletRequest servletRequest, ServletResponse servletResponse, FilterChain filterChain) throws IOException, ServletException {
        printBasicInfo(servletRequest);
        //获取token
        HttpServletRequest request = (HttpServletRequest) servletRequest;
        if ("OPTIONS".equals(request.getMethod())) {
            log.info("跨域请求");
            filterChain.doFilter(servletRequest, servletResponse);
            return;
        }
        String path = request.getRequestURI();
        Boolean isLogin = false;
        for (String white : whiteList.getWhite()) {
            if (RegexUtils.findRegex(path, white)) {
                isLogin = true;
                break;
            }
        }
        if (isLogin) {
            filterChain.doFilter(servletRequest, servletResponse);
        } else {
            String token = request.getHeader("token");
            if (StringUtil.isEmpty(token)) {
                throw new PassErrorException("token或csrfToken未携带");
            }
            if(JwtUtils.validateJwtToken(token)){
                String userId = (String) JwtUtils.parseJwtToken(token).get("userId");
                //从redis中获取用户信息
                String jwt = redisUserService.getCacheToken(userId);
                if(jwt==null){
                    throw new PassErrorException("TOKEN错误");
                }else if(!jwt.equals(token)){
                    throw new PassErrorException("TOKEN错误");
                }else{
                    //存入ThreadLocal
                    threadLocalUtil.setUser(userId);
                    filterChain.doFilter(servletRequest, servletResponse);
                    threadLocalUtil.clear();
                }
            }else{
                throw new PassErrorException("TOKEN错误");
            }
        }
    }

    @Override
    public void destroy() {
        Filter.super.destroy();
    }
}
